use tauri::State;
use serde::{Deserialize, Serialize};
use tracing::{info, error, debug};
use chrono::{DateTime, Utc};

use crate::database::DatabaseManager;
use crate::database::schema::{Task, TaskLog};
use crate::error::{AppError, Result as AppResult};

#[derive(Debug, Serialize, Deserialize)]
pub struct TaskResponse {
    pub id: String,
    pub name: String,
    pub task_type: String,
    pub category: String,
    pub account_id: String,
    pub device_id: Option<String>,
    pub status: String,
    pub priority: i32,
    pub scheduled_at: Option<String>,
    pub started_at: Option<String>,
    pub completed_at: Option<String>,
    pub progress: Option<TaskProgressResponse>,
    pub error_message: Option<String>,
    pub created_at: String,
    pub updated_at: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TaskProgressResponse {
    pub completed: i32,
    pub total: i32,
    pub percentage: i32,
    pub current_step: Option<String>,
}

impl From<Task> for TaskResponse {
    fn from(task: Task) -> Self {
        let progress = if task.total_steps > 0 {
            Some(TaskProgressResponse {
                completed: (task.progress_percentage * task.total_steps / 100).max(0) as i32,
                total: task.total_steps as i32,
                percentage: task.progress_percentage as i32,
                current_step: task.current_step.clone(),
            })
        } else {
            None
        };

        Self {
            id: task.id,
            name: task.name,
            task_type: task.task_type,
            category: task.category,
            account_id: task.account_id,
            device_id: task.device_id,
            status: task.status,
            priority: task.priority as i32,
            scheduled_at: task.scheduled_at.map(|dt| dt.format("%Y-%m-%d %H:%M:%S UTC").to_string()),
            started_at: task.started_at.map(|dt| dt.format("%Y-%m-%d %H:%M:%S UTC").to_string()),
            completed_at: task.completed_at.map(|dt| dt.format("%Y-%m-%d %H:%M:%S UTC").to_string()),
            progress,
            error_message: task.error_message,
            created_at: task.created_at.format("%Y-%m-%d %H:%M:%S UTC").to_string(),
            updated_at: task.updated_at.format("%Y-%m-%d %H:%M:%S UTC").to_string(),
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CreateTaskRequest {
    pub name: String,
    pub task_type: String,
    pub account_id: String,
    pub device_id: Option<String>,
    pub priority: Option<i32>,
    pub scheduled_at: Option<i64>, // Unix timestamp
    pub config: serde_json::Value,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TaskLogResponse {
    pub id: i64,
    pub task_id: String,
    pub level: String,
    pub message: String,
    pub details: Option<String>,
    pub step_name: Option<String>,
    pub timestamp: String,
}

impl From<TaskLog> for TaskLogResponse {
    fn from(log: TaskLog) -> Self {
        Self {
            id: log.id,
            task_id: log.task_id,
            level: log.log_level,
            message: log.message,
            details: log.details,
            step_name: log.step_name,
            timestamp: log.timestamp.format("%Y-%m-%d %H:%M:%S UTC").to_string(),
        }
    }
}

/// 获取任务列表
#[tauri::command]
pub async fn get_tasks(
    status: Option<String>,
    limit: Option<i32>,
    offset: Option<i32>,
    db: State<'_, DatabaseManager>
) -> Result<Vec<TaskResponse>, String> {
    info!("Fetching tasks list with status filter: {:?}", status);
    
    let limit = limit.unwrap_or(50);
    let offset = offset.unwrap_or(0);
    
    match db.get_tasks(status, limit, offset).await {
        Ok(tasks) => {
            let task_responses: Vec<TaskResponse> = tasks
                .into_iter()
                .map(TaskResponse::from)
                .collect();
            
            debug!("Retrieved {} tasks", task_responses.len());
            Ok(task_responses)
        }
        Err(e) => {
            error!("Failed to fetch tasks: {}", e);
            Err(format!("Failed to fetch tasks: {}", e))
        }
    }
}

/// 创建新任务
#[tauri::command]
pub async fn create_task(
    request: CreateTaskRequest,
    db: State<'_, DatabaseManager>
) -> Result<String, String> {
    info!("Creating task: {}", request.name);
    
    let scheduled_at = request.scheduled_at.map(|ts| {
        chrono::DateTime::from_timestamp(ts, 0)
            .map(|dt| dt.naive_utc())
            .unwrap_or_else(|| chrono::Utc::now().naive_utc())
    });
    
    let task = Task {
        id: uuid::Uuid::new_v4().to_string(),
        name: request.name,
        task_type: request.task_type,
        category: "default".to_string(),
        strategy_id: None,
        account_id: request.account_id,
        device_id: request.device_id,
        parent_task_id: None,
        status: "pending".to_string(),
        priority: request.priority.unwrap_or(0) as i64,
        scheduled_at,
        deadline: None,
        config: serde_json::to_string(&request.config).unwrap(),
        input_data: None,
        output_data: None,
        started_at: None,
        completed_at: None,
        execution_duration: None,
        retry_count: 0,
        max_retries: 3,
        retry_delay: 30,
        error_message: None,
        error_code: None,
        error_details: None,
        progress_percentage: 0,
        current_step: None,
        total_steps: 0,
        created_at: chrono::Utc::now().naive_utc(),
        updated_at: chrono::Utc::now().naive_utc(),
    };
    
    let task_id = task.id.clone();
    match db.create_task(&task).await {
        Ok(_) => {
            info!("Task created successfully: {}", task_id);
            Ok(task_id)
        }
        Err(e) => {
            error!("Failed to create task: {}", e);
            Err(format!("Failed to create task: {}", e))
        }
    }
}

/// 开始执行任务
#[tauri::command]
pub async fn start_task(
    task_id: String,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    info!("Starting task: {}", task_id);
    
    match db.update_task_status(&task_id, "running").await {
        Ok(_) => {
            // 记录任务开始日志
            let log = TaskLog {
                id: 0, // Auto-generated
                task_id: task_id.clone(),
                log_level: "info".to_string(),
                message: "Task started".to_string(),
                details: None,
                step_name: None,
                step_index: None,
                screenshot_path: None,
                attachments: None,
                timestamp: chrono::Utc::now().naive_utc(),
            };
            let _ = db.create_task_log(&log).await;
            
            info!("Task started successfully: {}", task_id);
            Ok(())
        }
        Err(e) => {
            error!("Failed to start task: {}", e);
            Err(format!("Failed to start task: {}", e))
        }
    }
}

/// 暂停任务
#[tauri::command]
pub async fn pause_task(
    task_id: String,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    info!("Pausing task: {}", task_id);
    
    match db.update_task_status(&task_id, "paused").await {
        Ok(_) => {
            let log = TaskLog {
                id: 0,
                task_id: task_id.clone(),
                log_level: "info".to_string(),
                message: "Task paused".to_string(),
                details: None,
                step_name: None,
                step_index: None,
                screenshot_path: None,
                attachments: None,
                timestamp: chrono::Utc::now().naive_utc(),
            };
            let _ = db.create_task_log(&log).await;
            
            info!("Task paused successfully: {}", task_id);
            Ok(())
        }
        Err(e) => {
            error!("Failed to pause task: {}", e);
            Err(format!("Failed to pause task: {}", e))
        }
    }
}

/// 完成任务
#[tauri::command]
pub async fn complete_task(
    task_id: String,
    result: Option<serde_json::Value>,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    info!("Completing task: {}", task_id);
    
    match db.update_task_status(&task_id, "completed").await {
        Ok(_) => {
            // TODO: implement update_task_progress method
            
            let log = TaskLog {
                id: 0,
                task_id: task_id.clone(),
                log_level: "info".to_string(),
                message: "Task completed successfully".to_string(),
                details: result.as_ref().map(|r| r.to_string()),
                step_name: None,
                step_index: None,
                screenshot_path: None,
                attachments: None,
                timestamp: chrono::Utc::now().naive_utc(),
            };
            let _ = db.create_task_log(&log).await;
            
            info!("Task completed successfully: {}", task_id);
            Ok(())
        }
        Err(e) => {
            error!("Failed to complete task: {}", e);
            Err(format!("Failed to complete task: {}", e))
        }
    }
}

/// 任务执行失败
#[tauri::command]
pub async fn fail_task(
    task_id: String,
    error_message: String,
    error_code: Option<String>,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    info!("Marking task as failed: {}", task_id);
    
    // TODO: implement record_task_error method
    match db.update_task_status(&task_id, "failed").await {
        Ok(_) => {
            let log = TaskLog {
                id: 0,
                task_id: task_id.clone(),
                log_level: "error".to_string(),
                message: "Task failed".to_string(),
                details: Some(error_message),
                step_name: None,
                step_index: None,
                screenshot_path: None,
                attachments: None,
                timestamp: chrono::Utc::now().naive_utc(),
            };
            let _ = db.create_task_log(&log).await;
            
            info!("Task marked as failed: {}", task_id);
            Ok(())
        }
        Err(e) => {
            error!("Failed to mark task as failed: {}", e);
            Err(format!("Failed to fail task: {}", e))
        }
    }
}

/// 重试任务
#[tauri::command]
pub async fn retry_task(
    task_id: String,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    info!("Retrying task: {}", task_id);
    
    // TODO: implement retry_task method  
    match db.update_task_status(&task_id, "pending").await {
        Ok(_) => {
            let log = TaskLog {
                id: 0,
                task_id: task_id.clone(),
                log_level: "info".to_string(),
                message: "Task retry initiated".to_string(),
                details: None,
                step_name: None,
                step_index: None,
                screenshot_path: None,
                attachments: None,
                timestamp: chrono::Utc::now().naive_utc(),
            };
            let _ = db.create_task_log(&log).await;
            
            info!("Task retry initiated: {}", task_id);
            Ok(())
        }
        Err(e) => {
            error!("Failed to retry task: {}", e);
            Err(format!("Failed to retry task: {}", e))
        }
    }
}

/// 更新任务进度
#[tauri::command]
pub async fn update_task_progress(
    task_id: String,
    percentage: i32,
    current_step: Option<String>,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    debug!("Updating task progress: {} - {}%", task_id, percentage);
    
    // TODO: implement update_task_progress method
    Ok(()) // Placeholder
}

/// 删除任务
#[tauri::command]
pub async fn delete_task(
    task_id: String,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    info!("Deleting task: {}", task_id);
    
    // TODO: 实现实际的任务删除逻辑
    // 需要检查任务状态，正在运行的任务不能直接删除
    
    Ok(())
}

/// 获取任务日志
#[tauri::command]
pub async fn get_task_logs(
    task_id: String,
    limit: Option<i32>,
    db: State<'_, DatabaseManager>
) -> Result<Vec<TaskLogResponse>, String> {
    debug!("Fetching logs for task: {}", task_id);
    
    let limit = limit.unwrap_or(100);
    
    match db.get_task_logs(&task_id, limit).await {
        Ok(logs) => {
            let log_responses: Vec<TaskLogResponse> = logs
                .into_iter()
                .map(TaskLogResponse::from)
                .collect();
            
            debug!("Retrieved {} logs for task {}", log_responses.len(), task_id);
            Ok(log_responses)
        }
        Err(e) => {
            error!("Failed to fetch task logs: {}", e);
            Err(format!("Failed to fetch task logs: {}", e))
        }
    }
}

/// 添加任务日志
#[tauri::command]
pub async fn add_task_log(
    task_id: String,
    level: String,
    message: String,
    details: Option<String>,
    step_name: Option<String>,
    db: State<'_, DatabaseManager>
) -> Result<(), String> {
    debug!("Adding log for task {}: {}", task_id, message);
    
    let log = TaskLog {
        id: 0,
        task_id,
        log_level: level,
        message,
        details,
        step_name,
        step_index: None,
        screenshot_path: None,
        attachments: None,
        timestamp: chrono::Utc::now().naive_utc(),
    };
    match db.create_task_log(&log).await {
        Ok(_) => Ok(()),
        Err(e) => {
            error!("Failed to add task log: {}", e);
            Err(format!("Failed to add task log: {}", e))
        }
    }
}

/// 获取任务统计信息
#[tauri::command]
pub async fn get_task_stats(
    db: State<'_, DatabaseManager>
) -> Result<serde_json::Value, String> {
    debug!("Fetching task statistics");
    
    match db.get_task_stats().await {
        Ok(stats) => Ok(stats),
        Err(e) => {
            error!("Failed to fetch task stats: {}", e);
            Err(format!("Failed to fetch task stats: {}", e))
        }
    }
}